package org.herui.campus.service.service;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.shan.spring.redis.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

public abstract class BaseRedisRegionsTimeCountService {

    protected SimpleDateFormat ymdh = new SimpleDateFormat("yyyy-MM-dd HH");
   protected SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd");

    @Autowired
    RedisUtil<Object> redisUtil;

    /**
     * user:registered:china 1 time
     *
     * hash
     * // 存储每个用户的时间  到24点的时候清除
     * user:registered:china:day 1 time
     * // 存储每个小时的总数
     * user:registered:china:hourcount time/60000 cout++
     * // 存储每天的总数
     * user:registered:china:daycount time/3600000 cout++
     */

    protected String prefx = "iot:statis:user:regis:";

    // 每个物体或者用户最新的时间记录
//    protected String regionTimeKey = "user:registered:last:";
    // user:registered:%s:id 存储每个用户的时间  到24点的时候清除
    protected String timeIdDayKey = "user:registered:id:";
    // 不同区域每个小时记录
    protected String regionHourCountKey = "user:registered:%s:hourcount";
    // 所有区域每个小时记录
    protected String hourCountKey = "user:registered:hourcount";
    // 不同区域每天记录
    protected String regionDayCountKey = "user:registered:%s:daycount";
    // 所有区域每天记录
    protected String dayCountKey = "user:registered:daycount";

    @PostConstruct
    public void init(){
        prefx = getPrefx();
//        regionTimeKey = prefx+"last:";
        timeIdDayKey = prefx+"idday:";
        regionHourCountKey = prefx+"%s:hourcount";
        hourCountKey = prefx+"hourcount";
        regionDayCountKey = prefx+"%s:daycount";
        dayCountKey = prefx+"daycount";
    }

    protected abstract String getPrefx();

    /**
     * 添加数据
     * @param id        唯一标识
     * @param region    区域
     * @param time      时间
     */
    public void add(String id, String region, long time){

//        String key = regionTimeKey+region;
//        redisUtil.getRedisTemplate().opsForZSet().add(key, id, time /1000);
//        key = regionTimeKey+"all";
//        redisUtil.getRedisTemplate().opsForZSet().add(key, id, time /1000);

        // 保存个体时间
        String key = timeIdDayKey +region;
        Boolean absent = redisUtil.getRedisTemplate().opsForHash().putIfAbsent(key, id, time / 1000);
        if (absent){
            // 设置这个key的到期时间为 今天
            redisUtil.getRedisTemplate().expireAt(key, DateUtil.endOfDay(new Date()));
            // 这个小时 +1
            key = regionHourCountKey.replace("%s", region);
            String timeKey = ymdh.format(new Date(time));
            redisUtil.getRedisTemplate().opsForHash().increment(key, timeKey, 1);
            // 全部的这个小时+1
            key = hourCountKey;
            redisUtil.getRedisTemplate().opsForHash().increment(key, timeKey, 1);

            // 今天+1
            key = regionDayCountKey.replace("%s", region);
            timeKey = ymd.format(new Date(time));
            redisUtil.getRedisTemplate().opsForHash().increment(key, timeKey, 1);
            key = dayCountKey;
            redisUtil.getRedisTemplate().opsForHash().increment(key, timeKey, 1);
        }
    }

    /**
     * 获取整体的统计数据
     * @param startTime
     * @param endTime
     * @param region
     * @return
     */
//    public int getTotalCount(Long startTime, Long endTime, String region){
//        Long count;
//        if (StringUtils.isEmpty(region)){
//            count = redisUtil.getRedisTemplate().opsForZSet().count(regionTimeKey + "all", startTime / 1000,
//                    endTime / 1000);
//        }else{
//            count = redisUtil.getRedisTemplate().opsForZSet().count(regionTimeKey + region, startTime / 1000,
//                    endTime / 1000);
//        }
//        return count.intValue();
//    }

    /**
     * 获取当天每个小时的数据
     * @param region
     * @return
     */
    public List<Result> listHour(String region){

        Calendar calendar = Calendar.getInstance();
        String key = hourCountKey;
        // 获取具体区域的数据
        if (!StringUtils.isEmpty(region)){
            key = regionHourCountKey.replace("%s", region);
        }
        List<Object> timeKeys = new LinkedList<>();
        List<Result> results = new LinkedList<>();
        for (int i = 0; i < 24; i++) {
            calendar.set(Calendar.HOUR_OF_DAY, i);
            String timeKey = ymdh.format(calendar.getTime());
            timeKeys.add(timeKey);
            Result result = new Result(calendar.getTime().getTime(), null);
            results.add(result);
        }
        List<Object> objects = redisUtil.getRedisTemplate().opsForHash().multiGet(key, timeKeys);
        for (int i = 0; i < objects.size(); i++) {
//            System.out.println(timeKeys.get(i)+"------"+objects.get(i));
            results.get(i).count = objects.get(i);
            if (results.get(i).count == null){
                results.get(i).count = 0;
            }
        }
        return results;
    }

    /**
     * 根据实际戳获取
     * @param region
     * @param startTime
     * @param endTime
     * @return
     */
    public List<Result> listDay(String region, Long startTime, Long endTime){

        Calendar calendar = Calendar.getInstance();
        String key = dayCountKey;
        // 获取具体区域的数据
        if (!StringUtils.isEmpty(region)){
            key = regionDayCountKey.replace("%s", region);
        }
        List<Object> timeKeys = new LinkedList<>();
        List<Result> results = new LinkedList<>();

        calendar.setTime(new Date(startTime));
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);

        while (calendar.getTime().getTime() < endTime){
            String timeKey = ymd.format(calendar.getTime());
            timeKeys.add(timeKey);
            Result result = new Result(calendar.getTime().getTime(), null);
            results.add(result);
            calendar.add(Calendar.DAY_OF_YEAR, 1);
        }
        List<Object> objects = redisUtil.getRedisTemplate().opsForHash().multiGet(key, timeKeys);
        for (int i = 0; i < objects.size(); i++) {
//            System.out.println(timeKeys.get(i)+"------"+objects.get(i));
            results.get(i).count = objects.get(i);
            if (results.get(i).count == null){
                results.get(i).count = 0;
            }
        }
        return results;
    }

    public List<Result> listDay(String region, List<String> days){

        Calendar calendar = Calendar.getInstance();
        String key = dayCountKey;
        // 获取具体区域的数据
        if (!StringUtils.isEmpty(region)){
            key = regionDayCountKey.replace("%s", region);
        }
        List<Object> timeKeys = new LinkedList<>();
        List<Result> results = new LinkedList<>();

        for (String day: days){
            timeKeys.add(day);
            Result result = new Result(calendar.getTime().getTime(), null);
            results.add(result);
        }
        List<Object> objects = redisUtil.getRedisTemplate().opsForHash().multiGet(key, timeKeys);
        for (int i = 0; i < objects.size(); i++) {
//            System.out.println(timeKeys.get(i)+"------"+objects.get(i));
            results.get(i).count = objects.get(i);
            if (results.get(i).count == null){
                results.get(i).count = 0;
            }
        }
        return results;
    }

    /**
     * 清空个人每天的记录
     */
    public void clearIdKey(){
        redisUtil.delMutil(timeIdDayKey);
    }

    public static void main(String[] args) {
        long l = System.currentTimeMillis() / (24 * 60 * 60 * 1000);
        l = l*(24 * 60 * 60 * 1000);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        System.out.println(dateFormat.format(DateUtil.endOfDay(new Date())));
    }

    @Data
    public static class Result{
        public Long time;
        public Object count;

        public Result(Long time, Object count) {
            this.time = time;
            this.count = count;
        }
    }
}
